﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using Microsoft.Win32;

namespace SystemScanner.ClientServices
{
	public static class RegistryService
	{
		#region Methods

		// Public Methods 

		/// <summary>
		/// Iterates the subkeys of keyName. For each subkey, iterates its value names, passing those
		/// back to the caller as part of creationFunc, allowing caller to retrieve the value names
		/// and their associated values so it can build whatever Tdata in whatever way it requires.
		/// </summary>
		/// <typeparam name="Tdata">The type of the data.</typeparam>
		/// <param name="keyName">Name of the Registry key.</param>
		/// <param name="creator">Callback function that knows how to create/initialize instances of Tdata.</param>
		/// <returns></returns>
		public static IEnumerable<Tdata> QueryBySubkeys<Tdata>(string keyName, Func<Func<string, string>, Tdata> creator)
		{
			var regKey = Registry.LocalMachine.OpenSubKey(keyName);

			if (regKey == null)
            {
            	yield break;
            }

			foreach (var subKeyName in regKey.GetSubKeyNames())
			{
				var subKey = regKey.OpenSubKey(subKeyName);
		
				// the caller will use this function to get values for the names it is interested in.
				Func<string, string> valueGetter = (k) =>
				{
					if (string.Compare(k, "identifier", true) == 0)
                    {
						return subKeyName;
                    }
					return subKey.GetValue(k) as string;
				};

				yield return creator(valueGetter);
			}
		}

		/// <summary>
		/// Queries by the values contained in the registry key.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="keyName">Name of the registry key.</param>
		/// <param name="creator">Callback function that knows how to create/initialize instances of Tdata.</param>
		/// <returns></returns>
		public static IEnumerable<T> QueryByValues<T>(string keyName, Func<string, object, T> creator)
		{
			var regKey = Registry.LocalMachine.OpenSubKey(keyName);

			if (regKey == null)
			{
				yield break;
			}

			foreach (var valueName in regKey.GetValueNames())
			{
				T t = creator(valueName, regKey.GetValue(valueName));
				
				yield return t;
			}
		}

		#endregion Methods
	}
}
